﻿using Minio;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;

namespace Baby.Shop.Util
{
    public class MinioClientWrapper
    {
        private static MinioClient _minioClient;
        public string endpoint;
        public string accessKey;
        public string secretKey;
        /// <summary>
        /// string endpoint, string accessKey, string secretKey
        /// </summary>
        public MinioClientWrapper(string endpoint, string accessKey, string secretKey)
        {
            _minioClient = new MinioClient()
                .WithEndpoint(endpoint)
                .WithCredentials(accessKey, secretKey)
                .Build();
        }
        /// <summary>
        /// 创建桶
        /// </summary>
        /// <param name="bucketName"></param>
        /// <returns></returns>
        public static async Task CreateBucketAsync(string bucketName)
        {
            var beArgs = new BucketExistsArgs()
                     .WithBucket(bucketName);
            bool found = await _minioClient.BucketExistsAsync(beArgs);
            if (!found)
            {
                var mbArgs = new MakeBucketArgs()
                    .WithBucket(bucketName);
                await _minioClient.MakeBucketAsync(mbArgs);
            }
        }
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="bucketName"></param>
        /// <param name="objectName"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static async Task UploadFileAsync(Stream stream, string bucketName, string objectName, string contentType)
        {
            try
            {
                await CreateBucketAsync(bucketName);
                var putObjectArgs = new PutObjectArgs()
                      .WithBucket(bucketName)
                      .WithObject(objectName)
                      .WithStreamData(stream)
                      .WithObjectSize(stream.Length)
                      .WithContentType(contentType);
                await _minioClient.PutObjectAsync(putObjectArgs);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        /// <summary>
        /// 获取文件
        /// </summary>
        /// <param name="bucketName"></param>
        /// <param name="objectName"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static async Task<MinioFileResult> DownloadFileAsync(string bucketName, string objectName)
        {
            try
            {
                MemoryStream ms = new MemoryStream();
                GetObjectArgs getObject = new GetObjectArgs()
                    .WithBucket(bucketName)
                    .WithObject(objectName)
                    .WithCallbackStream(x =>
                    {
                        x.CopyTo(ms);
                    });
                var objectStat = await _minioClient.GetObjectAsync(getObject);
                ms.Seek(0, SeekOrigin.Begin);
                ms.Dispose();
                return new MinioFileResult { ContentType = objectStat.ContentType, FileByte = ms.ToArray() };
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }
        /// <summary>
        /// 获取临时文件
        /// </summary>
        /// <param name="bucketName"></param>
        /// <param name="objectName"></param>
        /// <param name="expiry">秒1天24小时60分钟*60秒</param>
        /// <returns></returns>
        public static async Task<string> GetTempFileAsync(string bucketName, string objectName,int expiry =24*60*60)
        {
            PresignedGetObjectArgs presignedGetObject = new PresignedGetObjectArgs()
                .WithBucket(bucketName)
                .WithObject(objectName)
                .WithExpiry(expiry);
           return await _minioClient.PresignedGetObjectAsync(presignedGetObject);
        }
        /// <summary>
        /// 分块上传文件
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="bucketName"></param>
        /// <param name="objectName"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static async Task UploadFileByBlockAsync(Stream stream, string bucketName, string objectName, string contentType)
        {
            try
            {

                await CreateBucketAsync(bucketName);
                var putObjectArgs = new PutObjectArgs()
                      .WithBucket(bucketName)
                      .WithObject(objectName)
                      .WithStreamData(stream)
                      .WithObjectSize(stream.Length)
                      .WithContentType(contentType);
                await _minioClient.PutObjectAsync(putObjectArgs);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        /// <summary>
        /// 通过后缀名获取contentType
        /// </summary>
        /// <param name="suffix"></param>
        /// <returns></returns>
        public static string GetContentType(string suffix)
        {
            if (string.IsNullOrEmpty(suffix))
                return null;
            string contentType = string.Empty;
            switch (suffix.ToLower())
            {
                case ".png":
                    contentType = "image/png";
                    break;
                case ".jpg":
                    contentType = "image/jpeg";
                    break;
                case ".jpeg":
                    contentType = "image/jpeg";
                    break;
                case ".gif":
                    contentType = "image/gif";
                    break;
                case ".pdf":
                    contentType = "application/pdf";
                    break;
                case ".docx":
                    contentType = "application/msword";
                    break;
                default:
                    contentType = "application/octet-stream";
                    break;
            }
            return contentType;
        }
        public class MinioFileResult
        {
            public string ContentType { get; set; }

            public string FileName { get; set; }

            public byte[] FileByte { get; set; }
        }

        public class ContentTypeMethod
        {

        }
    }
}
